package com.google.code.virtualhockey.vhx.server.servlet.rest

import javax.servlet.http.{HttpServletResponse, HttpServletRequest}
import java.util.Locale

/**
 * Represents a REST command request. The creation of a RestCommandRequest is guaranteed to always
 * succeed. However calling a particular method or accessing a member may result in an Exception.
 */
class RestCommandRequest protected[rest] ( val httpRequest: HttpServletRequest,
                                           val httpResponse: HttpServletResponse ) {

  /** Name of the invoked command as Option. */
  val optCommand: Option[String] = {
    val tmp = httpRequest.getParameter( "cmd" )
    if ( tmp != null && tmp.length() > 0 )
      Some( tmp )
    else
      None
  }

  /**
   * Returns the name of the provided request command.
   */
  def command: String = {
    if ( optCommand == None )
      throw new RestCommandException( "No parameter 'cmd' is set." )
    optCommand.get
  }

  /** Locale that has explicitly been provided by the caller. */
  lazy val optLocale: Option[Locale] = {
    val tmp = httpRequest.getParameter( "loc" )
    if ( tmp == null )
      None
    else {
      val astrParts = tmp.split( "_" )

      // check language
      //
      val strLanguage = astrParts(0).toLowerCase
      if ( strLanguage.length() != 2 )
        throw new RestCommandException( "Language part of submitted locale must be a two character ISO 639 code." )
      if ( !Locale.getISOLanguages.contains( strLanguage ) )
        throw new RestCommandException( "Language '" + strLanguage + "' is not a known ISO 639 code." )

      // check country
      //
      val optCountry = if ( astrParts.size > 1 ) {
        val tmp = astrParts(1).toLowerCase
        if ( tmp.length() != 2 )
          throw new RestCommandException( "Country part of submitted locale must be a two character ISO 3166 code." )
        if ( !Locale.getISOCountries.contains( tmp ) )
          throw new RestCommandException( "Country '" + tmp + "' is not a known ISO 3166 code." )
        Some( tmp )
      } else {
        None
      }

      if ( optCountry != None )
        Some( new Locale( strLanguage, optCountry.get ) )
      else
        Some( new Locale( strLanguage ) )
    }
  }

  /** Security token to be used to protect against XSRF attacks. */
  lazy val optSecurityToken: Option[String] = {
    val tmp = httpRequest.getParameter( "sec" )
    if ( tmp != null && tmp.length() > 0 )
      Some( tmp )
    else
      None
  }

  /** JSON-P callback name (if any it is used to pad the result) */
  lazy val optJsonpCallbackSuccess: Option[String] = {
    val tmp = httpRequest.getParameter( "cbs" )
    if ( tmp != null && tmp.length() > 0 )
      Some( tmp )
    else
      None
  }

  /** JSON-P error callback name (if any it is used to pad the given error result) */
  lazy val optJsonpCallbackError: Option[String] = {
    val tmp = httpRequest.getParameter( "cbe" )
    if ( tmp != null && tmp.length() > 0 )
      Some( tmp )
    else
      None
  }
}
